<template>
  <div class="console-container">
    <el-input
      ref="textareaRef"
      v-model="logContent"
      type="textarea"
      class="console"
      readonly
      @wheel="stopAutoScroll"
      @mousedown="stopAutoScroll"
    />
    <div class="button">
      <el-tooltip
        content="滚动到底部"
        :enterable="false"
        popper-class="padding-10-15"
      >
        <el-button type="info" @click="startAutoScroll">
          <ac-icon iconId="018ece4f702b32a39f8d" />
        </el-button>
      </el-tooltip>
      <el-tooltip
        content="清空"
        :enterable="false"
        popper-class="padding-10-15"
      >
        <el-button type="info" @click="clearLogger">
        <ac-icon iconId="018dc9c3efd3a0502886" />
        </el-button>
      </el-tooltip>
    </div>
  </div>
</template>

<script setup>
import { ref, nextTick, onMounted, onUnmounted } from 'vue';
import websocket from "@/utils/websocket";
import emitter from "@/utils/bus";

const textareaRef = ref();
const logContent = ref('');
const lock = ref(Promise.resolve());
const maxLength = 100000;
const autoScrollEnd = ref(true);

const showLogger = async(message) => {
  await lock.value;

  let hasChange = false;
  const textarea = textareaRef.value.$el.querySelector("textarea");
  const selectionStart = textarea.selectionStart;
  const selectionEnd = textarea.selectionEnd;

  logContent.value += message;
  if (logContent.value.length > maxLength) {
    hasChange = true;
    const start = logContent.value.length - maxLength;
    logContent.value = logContent.value.substring(logContent.value.indexOf('\n', start) + 1);
  }

  autoScrollEnd.value && await nextTick(() => textarea.scrollTop = textarea.scrollHeight);
  textareaRef.value.focus();
  !hasChange && await nextTick(() => textarea.setSelectionRange(selectionStart, selectionEnd));
  lock.value = Promise.resolve();
};

const clearLogger = () => {
  logContent.value = '';
};

const startAutoScroll = () => {
  try {
    const textarea = textareaRef.value.$el.querySelector("textarea");
    textarea.scrollTop = textarea.scrollHeight;
  } finally {
    autoScrollEnd.value = true;
  }
};

const stopAutoScroll = () => {
  autoScrollEnd.value = false;
};

onMounted(() => {
  websocket.connect();
  websocket.addTopics(["subscribe.logger"]);
  emitter.off('logger', res => showLogger(res));
  emitter.on('logger', res => showLogger(res));
});

onUnmounted(() => {
  emitter.off('logger', res => showLogger(res));
  websocket.close();
});
</script>

<style lang="scss" scoped>
.console-container {
  display: flex;
  width: 100vw;
  height: 100vh;

  .console {
    border: none!important;

    :deep(.el-textarea__inner) {
      width: 100%;
      height: 100%;
      resize: none;
      padding: 5px!important;
      border: none!important;
      border-radius: 0!important;
      box-shadow: none!important;
      background-color: #303133;
      color: #c5c5c5 !important;
      overflow-x: hidden;
      overflow-y: scroll;
    }
  }

  .button {
    position: absolute;
    bottom: 5px;
    right: 5px;
  }
}
</style>
